package com.doctcloud.common.core.utils;

import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class NumberUtils {

    // 处理 Double 类型（静态方法，支持直接调用）
    public static Double processDouble(Double value) {
        return processNumber(value, 0.0);
    }

    // 处理 Integer 类型
    public static Integer processInteger(Integer value) {
        return processNumber(value, 0);
    }

    // 处理 Long 类型
    public static Long processLong(Long value) {
        return processNumber(value, 0L);
    }

    // 处理 Float 类型
    public static Float processFloat(Float value) {
        return processNumber(value, 0.0f);
    }

    /**
     * 泛型核心方法：处理所有数值类型的空值（静态方法）
     * @param value 待处理的数值（可能为 null）
     * @param defaultValue 空值时的默认值（需与 value 类型一致）
     * @param <T> 数值类型（如 Double、Integer、Long 等）
     * @return 非 null 的数值（原值或默认值）
     */
    public static <T extends Number> T processNumber(T value, T defaultValue) {
        return ObjectUtils.isEmpty(value) ? defaultValue : value;
    }

    /**
     * Double四舍五入（指定小数位数，自动处理null值）
     * @param value 待处理的Double值（可能为null）
     * @param scale 保留的小数位数（如2表示保留两位小数）
     * @return 四舍五入后的结果（null时返回0.0）
     * @throws IllegalArgumentException 当scale为负数时抛出异常
     */
    public static Double roundDouble(Double value, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("保留的小数位数不能为负数: " + scale);
        }
        // 先处理空值（调用静态方法processDouble）
        Double processedValue = processDouble(value);
        // 使用BigDecimal避免浮点精度问题，四舍五入
        return new BigDecimal(processedValue.toString()) // 注意：用toString()避免Double转BigDecimal的精度损失
                .setScale(scale, RoundingMode.HALF_UP)
                .doubleValue();
    }

    /**
     * 扩展：支持自定义舍入模式的四舍五入方法
     * @param value 待处理的Double值（可能为null）
     * @param scale 保留的小数位数
     * @param roundingMode 舍入模式（如HALF_UP、UP、DOWN等）
     * @return 处理后的结果
     * @throws IllegalArgumentException 当scale为负数时抛出异常
     */
    public static Double roundDouble(Double value, int scale, RoundingMode roundingMode) {
        if (scale < 0) {
            throw new IllegalArgumentException("保留的小数位数不能为负数: " + scale);
        }
        Double processedValue = processDouble(value);
        return new BigDecimal(processedValue.toString())
                .setScale(scale, roundingMode)
                .doubleValue();
    }
}